package utils;

import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @program: merchant-neighbor
 * @description: List合并工具
 * @author: houlongwang
 * @create: 2019-09-16 18:43
 **/
@Slf4j
public class ListUtil {
    private ListUtil() {
    }

    /**
     * 带有“是否需要去重”选项的合并list方法
     * @param removeDuplicate 是否需要去重（true/false）
     * @param lists 需要合并的list
     * @param <T>
     * @return
     */
    public static <T> List<T> mergeListsTwo(boolean removeDuplicate, List<T>... lists) {
        Class clazz = lists[0].getClass();
        List<T> list = null;
        try {
            list = (List<T>) clazz.getDeclaredConstructor().newInstance();
        } catch (Exception e) {
            log.error("集合合并处理实例化异常：{}",e);
        }

        if (removeDuplicate) {
            // 移除重复数据
            removerDoubleData(list, lists);
        } else {
            // 不移除重复数据
            noRemoveDobleData(list, lists);
        }
        return list;
    }

    private static <T> void noRemoveDobleData(List<T> list, List<T>[] lists) {
        for (int i = 0, len = lists.length; i < len; i++) {
            if (null  != list) {
                list.addAll(lists[i]);
            }
        }
    }

    private static <T> void removerDoubleData(List<T> list, List<T>[] lists) {
        for (int i = 0, len = lists.length; i < len; i++) {
            Iterator it = lists[i].iterator(); // 迭代器
            while (it.hasNext()) {
                T obj = (T) it.next();
                if (null  != list && !list.contains(obj)) {
                    list.add(obj);
                }
            }
        }
    }

    /**
     * 合并list，默认不去除重复
     * @param lists
     * @param <T>
     * @return
     */
    public static <T> List<T> mergeListsTwo(List<T>... lists) {
        return mergeListsTwo(true, lists);
    }

    /**
     * 找到有值的集合并返回
     * @param lists
     * @param <T>
     * @return
     */
    public static <T> List<T> ifNull(List<T>... lists) {
        for (int i = 0, len = lists.length; i < len; i++) {
            Iterator it = lists[i].iterator();
            if (it.hasNext()) {
                return IteratorUtils.toList(it);
            }
        }
        return Lists.newArrayList();
    }

    /**
     * 对list分组，分成多个list<list>
     * @param list
     * @param <T>
     * @return
     */
    public static <T> List<List<T>> groupList(List list){
        int listSize = list.size();
        int toIndex = 100;
        List resultList = new ArrayList();
        for (int i = 0; i < list.size(); i += toIndex) {
            if (i + toIndex > listSize) {
                toIndex = listSize - i;
            }
            List newList = list.subList(i, i + toIndex);
            resultList.add(newList);
        }
        return resultList;
    }




    /**
     * 集合拆分
     * 小于等于limit不需要拆分
     *
     * @param list
     * @param limit
     * @param <E>
     * @return
     */
    public static <E> List<List<E>> splitList(List<E> list, final int limit) {
        if ( CollectionUtils.isEmpty(list)) {
            return Collections.emptyList();
        }

        final int listSize = list.size();
        final int count = listSize % limit == 0 ? listSize / limit : listSize / limit + 1;

        final List<List<E>> result = new ArrayList<>(count);

        if (listSize <= limit) {
            result.add(list);
            return result;
        }

        List<E> subList;
        for (int i = 0; i < count; i++) {
            subList = (i == count - 1) ? list.subList(i * limit, listSize)
                    : list.subList(i * limit, (i + 1) * limit);
            result.add(subList);
        }

        return result;
    }

    /**
     * 集合合并
     * @param list1
     * @param list2
     * @param <T>
     * @return
     */
    public static<T> List<T> mergeList(List<T> list1 ,List<T> list2){

        return Stream.concat(list1.stream(),list2.stream()).collect(Collectors.toList());
    }

}


